<template>
  <div>
    <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item>权限管理</el-breadcrumb-item>
        <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>

    <el-card class="box-card">
        <el-row>
            <el-col>
                <el-button type="primary" @click="addDialogVisible = true">添加角色</el-button>
            </el-col>
        </el-row>
        <el-table
            :data="RuleCompetenceList"
            style="width: 100%"
            border
            stripe>
            <!-- 展开列 -->
            <el-table-column type="expand">
                <template scope="{row}">
                    <el-row 
                    v-for="(item1,i1) in row.children" :key="item1.id"
                     :class="['bdBottom',i1 === 0 ? 'bdTop' : '']"
                     class="el-row-Unfold">
                        <!-- 一级权限列表 -->
                        <el-col :span="5">
                            <el-tag class="el-tag-Unfold"
                            @close="removeRightById(row,item1.id)"
                            closable>{{item1.authName}}</el-tag>
                            <i class="el-icon-caret-right"></i>
                        </el-col>
                        <!-- 二级和三级权限列表 -->
                        <el-col 
                        :span="19">
                            <el-row 
                            v-for="(item2,i2) in item1.children" 
                            :key="item2.id"
                            class="el-row-item"
                            :class="[i2 == item1.children.length-1 ? '' : 'bdBottom']">
                                <!-- 二级权限渲染 -->
                                <el-col :span="6">
                                    <el-tag
                                    @close="removeRightById(row,item2.id)"
                                    closable    
                                    type="success"
                                    class="el-tag-Unfold">{{item2.authName}}</el-tag>
                                    <i class="el-icon-caret-right"></i>
                                </el-col>
                                <!-- 三级权限渲染 -->
                                <el-col :span="18">
                                    <el-tag 
                                    @close="removeRightById(row,item3.id)"
                                    closable
                                    type="warning" 
                                    v-for="item3 in item2.children" :key="item3.id"
                                    class="el-tag-Unfold">{{item3.authName}}</el-tag>
                                </el-col>
                            </el-row>
                        </el-col>
                    </el-row>
                </template>
            </el-table-column>
            <!-- 索引列 -->
            <el-table-column
                label="#"
                type="index"
                width="50">
            </el-table-column>
            <el-table-column
                prop="roleName"
                label="角色名称"
                min-width>
            </el-table-column>
            <el-table-column
                prop="roleDesc"
                label="角色描述"
                min-width>
            </el-table-column>
            <el-table-column label="操作" width="288px">
                <template scope="{row}">
                    <!-- 编辑角色 -->
                    <el-button 
                    type="primary" 
                    icon="el-icon-edit" 
                    size="mini"
                    @click="edit(row.id)"
                    >编辑</el-button>
                    <!-- 删除角色 -->
                    <el-button 
                    type="danger" 
                    icon="el-icon-delete" 
                    size="mini"
                    @click="delRole(row)"
                    >删除</el-button>
                    <!-- 分配角色通过tooltip包裹了一下，将会hover后提示文字分配角色，enterable指是否允许进入提示信息框内 -->
                    <el-button 
                    type="warning" 
                    icon="el-icon-setting" 
                    size="mini"
                    @click="setRightShow(row)">分配权限</el-button>
                </template>
            </el-table-column>
        </el-table>
    </el-card>

    <!-- 点击添加角色提示dialog对话框 -->
    <el-dialog 
      :modal-append-to-body="false"
      title="创建角色"
      :visible.sync="addDialogVisible"
      width="40%"
      @close="addDialogReset"
      :close-on-click-modal="false"
      >
      <!-- 内容主体区 -->
      <el-form 
      :model="addRoleformData" 
      label-width="100px"
      :rules="addRoleformDataRules"
      ref="addFormRef"
      >
        <el-form-item 
        prop="roleName" 
        required 
        label="角色名称" 
        label-width="auto">
          <el-input v-model="addRoleformData.roleName" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item 
        prop="roleDesc" 
        label="角色描述" 
        label-width="auto">
          <el-input 
          v-model="addRoleformData.roleDesc" 
          autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer">
          <el-button @click="addDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="addRole">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 编辑角色_dialog对话框 -->
    <el-dialog 
    title="编辑角色信息" 
    :visible.sync="isdialogVisible"
    :modal-append-to-body="false"
    @close="editDialogReset"
    >
        <el-form 
        :model="editRoleformData"
        ref="editFormRef"
        :rules="editRoleformDataRules"
        label-width="100px">
            <!-- 角色名表单 -->
            <el-form-item 
            label="角色名称"
            prop="roleName"
            required>
                <el-input 
                v-model="editRoleformData.roleName">
                </el-input>
            </el-form-item>

            <!-- 编辑用户_描述表单 -->
            <el-form-item 
            label="角色描述" 
            prop="roleDesc">
                <el-input 
                v-model="editRoleformData.roleDesc">
                </el-input>
            </el-form-item>
        </el-form>    
        <span slot="footer">
            <el-button @click="isdialogVisible = false">取 消</el-button>
            <el-button type="primary" @click="editRole">确 定</el-button>
        </span>
    </el-dialog>

    <!-- 分配权限diaLog对话框 -->
    <el-dialog
    title="分配权限"
    :visible.sync="setRightDialogVisible"
    :modal-append-to-body="false"
    width="50%"
    :close-on-click-modal="false"
    @close="clearDefkeys">
        <el-tree 
        :data="setRightDataList" 
        :props="treeProps"
        show-checkbox
        node-key="id"
        default-expand-all
        :default-checked-keys="defkeys"
        ref="treeRef">
        <!-- node-key是指定所有选中的实际数据 -->
        </el-tree>
        <!-- 树形控件 -->
        <span slot="footer" class="dialog-footer">
            <el-button @click="setRightDialogVisible = false">取 消</el-button>
            <el-button type="primary" @click="setRightList">确 定</el-button>
        </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
    name:'Roles',
    data() {
        return {
            // 角色权限列表的数据
            RuleCompetenceList:[],
            // 控制添加角色的对话框遮罩层的开关
            addDialogVisible:false,
            // 添加角色diaLog中的表单验证数据
            addRoleformData:{
                roleName:'',
                roleDesc:'',
            },
            // 表单校验规则
            addRoleformDataRules:{
                roleName:[
                    {
                        required:true,
                        message:'输入不能为空！',
                        trigger:'blur',
                    },
                    {
                        min: 1,
                        max: 10,
                        message: "长度在 3 到 10 个字符",
                        trigger: "blur",
                    },     
                ],
                roleDesc:[
                    {
                        min: 0,
                        max: 20,
                        message: "长度在 0 到 20 个字符",
                        trigger: "blur",
                    },     
                ]
            },
            // 控制编辑角色的对话框显示与隐藏
            isdialogVisible:false,
            // 编辑角色diaLog中的表单验证数据
            editRoleformData:{
                roleName:'',
                roleDesc:'',
                roleId:''
            },
            // 表单校验规则
            editRoleformDataRules:{
                roleName:[
                    {
                        required:true,
                        message:'输入不能为空！',
                        trigger:'blur',
                    },
                    {
                        min: 2,
                        max: 10,
                        message: "长度在 2 到 10 个字符",
                        trigger: "blur",
                    },     
                ],
                roleDesc:[
                    {
                        min: 0,
                        max: 20,
                        message: "长度在 0 到 20 个字符",
                        trigger: "blur",
                    },     
                ]
            },
            // 控制分配权限diaLog对话框的显示与隐藏
            setRightDialogVisible:false,
            // 分配权限的权限列表树形结构数据
            setRightDataList:[],
            // 指定树形控件一些配置
            treeProps:{
                // children配置指定父子嵌套是根据哪个属性来嵌套的
                children:'children',
                // label配置指定我们所展示的数据是哪个属性
                label:'authName'
            },
            // 写入指定控件的唯一标识，这些标识会在展开树形控件时被默认选中
            defkeys:[],
            // 当前弹出dialog对话框的角色id
            currentRuleId:'',

        }
    },
    methods: {
        // 获取角色权限列表
        async getRuleCompetenceList(){
            const {data:res} = await this.$axios.get('roles');
            if(res.meta.status!==200) return this.$message.error(res.meta.msg)
            this.RuleCompetenceList = res.data;
            console.log(res.data);
        },
        // 监听用户点击确认添加角色，确认前需要进行一次表单的整体校验
        addRole(){
            // 通过ref选中form表单实例，调用validate方法对表单进行一次校验
            this.$refs.addFormRef.validate(async valid=>{
                if(!valid)return this.$message.error('格式错误')
                // 发起添加角色的网络请求
                const {data:res} = await this.$axios.post('roles',this.addRoleformData
                )
                // 判断请求结果是否失败
                if(res.meta.status!==201)return this.$message.error(res.meta.msg)
                // 提示请求成功
                this.$message.success(res.meta.msg);
                // 重新获取最新的角色列表
                this.getRuleCompetenceList();
                // 关闭diaLog消息框
                this.addDialogVisible = false;
            })
        },
        // 添加角色_监听关闭diaLog对话框时的事件
        addDialogReset(){
            // 当关闭diaLog时，重置表单验证和数据
            this.$refs.addFormRef.resetFields();
        },

        // 编辑角色_监听关闭diaLog对话框时的事件
        editDialogReset(){
            // 当关闭diaLog时，重置表单验证和数据
            this.$refs.editFormRef.resetFields();
        },
        // 监听用户单击编辑，弹出dialog对话框并且传入当前角色id
        edit(Id){
            // 显示对话框
            this.isdialogVisible = true;
            this.editRoleformData.roleId = Id;
        },
        // 监听编辑角色对话框中点击确认时对表单进行一次整体校验
        editRole(){
            this.$refs.editFormRef.validate(async valid=>{
                if(!valid)return this.$message.error('格式错误')
                const {data:res} = await this.$axios.put(`roles/${this.editRoleformData.roleId}`,this.editRoleformData
                )
                if(res.meta.status!==200)return this.$message.error(res.meta.msg)
                this.$message.success("编辑角色成功");
                this.getRuleCompetenceList();
                this.isdialogVisible = false;
            })
        },
        // 监听用户单击删除按钮，提示是否确认删除
        delRole(rowData){
            this.$messageBox.confirm('此操作将永久删除角色, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
                }).then(async () => {
                    // 点击确定后发起请求删除角色
                    const {data:res} = await this.$axios.delete(`roles/${rowData.id}`)
                    // 状态码不为200则删除失败，提示错误信息
                    if(res.meta.status!==200){
                       return this.$message.error(res.meta.msg);
                    }
                    // 删除成功后刷新角色列表
                    this.getRuleCompetenceList();
                    // 提示删除成功
                    this.$message({
                        type: 'success',
                        message: res.meta.msg
                    });
                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });          
                });
        },
        // 监听用户单击删除权限时触发，接收到当前角色的id和权限id
        async removeRightById(role,rightId){
            // 提示是否确定删除该权限
            this.$messageBox.confirm('此操作将永久删除该角色的该权限, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
                }).then(async () => {
                    // 点击确定后发起请求删除角色权限
                    const {data:res} = await this.$axios.delete(`roles/${role.id}/rights/${rightId}`)
                    // 判断是否成功删除权限
                    if(res.meta.status!==200) return this.$message.error(res.meta.msg)

                    // 成功删除权限后，返回最新的权限列表
                    role.children = res.data;

                    // 提示删除成功
                    this.$message({
                        type: 'success',
                        message: res.meta.msg
                    });
                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });          
                });
        },
        // 监听用户点击分配权限时弹出dialog对话框
        async setRightShow(rowData){
            // 获取所有权限数据
            const {data:res} = await this.$axios.get('rights/tree');
            if(res.meta.status!==200) return this.$message.error(res.meta.msg)
            
            // 获取当前角色所拥有的三级权限的所有id
            // console.log("rowData:",rowData);
            // for(const item2 of rowData.children){
            //     for(const item3 of item2.children){
            //         for(const item4 of item3.children){
            //             this.defkeys.push(item4.id)
            //         }
            //     }
            // }

            this.getThreeRightList(rowData,this.defkeys);
            this.currentRuleId = rowData.id;
            this.setRightDataList = res.data;
            this.setRightDialogVisible = true;
        },
        // 定义一个方法用于获取指定角色的所有三级权限
        getThreeRightList(node,arr){
            if(!node.children) return arr.push(node.id);
            
            // 递归
            node.children.forEach(item=>{
                this.getThreeRightList(item,arr);
            })
            
        },
        // 当用户关闭分配权限dialog时，清空当前的默认选中的控件
        clearDefkeys(){
            this.defkeys = []
        },
        // 当用户点击树形控件的确认时，触发当前函数
        async setRightList(roleId){
            const idArr = [...this.$refs.treeRef.getCheckedKeys(),...this.$refs.treeRef.getHalfCheckedKeys()];
            const idStr = idArr.join(',');
            console.log(idStr);

            const {data:res} = await this.$axios.post(`roles/${this.currentRuleId}/rights`,{
                rids:idStr
            });
            
            if(res.meta.status!==200) return this.$message.error(res.meta.msg);
            
            this.$message.success('更新权限成功');
            // 刷新角色列表
            this.getRuleCompetenceList();
            // 关闭dialog对话框
            this.setRightDialogVisible = false;
        }
    },
    created() {
        this.getRuleCompetenceList();
    },
}
</script>

<style lang="less" scoped>
.el-row-Unfold{
    margin: 0px 50px;
    display: flex;
    align-items: center;
}
.el-tag-Unfold{
    margin:7px;
}
.bdTop{
    border-top: 1px solid #eee;
}
.bdBottom{
    border-bottom: 1px solid #eee;
}
.el-row-item{
    display:flex;
    align-items: center;
}

</style>